////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __WN_NETWORK_MANAGER_WINDOWS_H__
#define __WN_NETWORK_MANAGER_WINDOWS_H__

#include "WNNetworking/inc/WNNetworkManager.h"
#include "WNConcurrency/inc/WNSpinMutex.h"

#include <vector>

namespace WNConcurrency {
    class WNThread;
}

namespace WNNetworking {
    class WNWindowsListenConnection;
    class WNWindowsINConnection;
    class WNWindowsConnection;
    class WNWindowsOutConnection;
    class WNNetworkManagerWindows : public WNNetworkManager {
    public:
        WNNetworkManagerWindows();
        virtual ~WNNetworkManagerWindows();

        virtual WNNetworkingError Initialize(WN_UINT32 _numWorkerThreads);
        virtual WNNetworkingError ConnectTo(WNConnection*& _outHandle, WNConnectionType _type, const WN_CHAR* _target, WN_UINT16 _port);
        virtual WNNetworkingError CreateListener(WNConnection*& _outHandle, WNConnectionType _type, WN_UINT16 _port, const WNConnectedCallback& _callback);
        virtual WN_VOID Cleanup();
        virtual WN_VOID DestroyConnection(WNConnection* _connection);
    private:
        static WN_VOID IOCPThread(WNNetworkManagerWindows* _manager);
        static WN_VOID ListenThread(WNNetworkManagerWindows* _manager);
        enum eWNWindowsInitializationState {
            eWNNotStarted,
            eWNWSAStartup,
            eWNAcceptEventCreated,
            eWNShutdownEventCreated,
            eWNIOCPCreated,
            eWNThreadsCreated,
            eWNInitializationCompleted
        };

        WN_UINT32 mMaxThreads;
        HANDLE mIOCP;
        HANDLE mAcceptEvent;
        HANDLE mShutdownEvent;
        eWNWindowsInitializationState mInitializationState;
        WNConcurrency::WNThread* mListenThread;
        WNConcurrency::WNSpinMutex mListenerMutex;
        WNConcurrency::WNSpinMutex mRecievedMutex;
        WNConcurrency::WNSpinMutex mInvalidMutex;
        WNConcurrency::WNSpinMutex mOutgoingMutex;

        std::vector<WNConcurrency::WNThread*> mThreads;
        std::list<WNWindowsListenConnection*> mIncommingConnections;
        std::list<WNWindowsOutConnection*> mOutgoingConnections;
        std::list<WNWindowsINConnection*> mReceivedConnections;
        std::list<WNConnection*> mInvalidConnections;
    };
};

#endif//__WN_NETWORK_MANAGER_WINDOWS_H__
